package br.com.ecomanda.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.hibernate.Criteria;
import org.hibernate.Session;

import br.com.ecomanda.exceptions.ConexaoComBancoDeDadosException;

@SuppressWarnings("unchecked")
public class GenericDao<T> {

	protected static EntityManager manager;
	
	protected Session session;

	static {
		EntityManagerFactory factory = Persistence
				.createEntityManagerFactory("EComanda");
		manager = factory.createEntityManager();
	}
	
	public GenericDao() throws ConexaoComBancoDeDadosException{
		try{
			this.session = (Session) manager.getDelegate();
		}
		catch (Exception e) {
			throw new ConexaoComBancoDeDadosException();
		}
	}

	public T getById(int id) {
		return (T) manager.find(getTypeClass(), id);
	}

	public void save(T entity) {
		session.flush();
		session.clear();
		
		try {
			manager.getTransaction().begin();
			manager.persist(entity);
			manager.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			manager.getTransaction().rollback();
		}
	}

	public T update(T entity) {
		session.flush();
		session.clear();
		
		T updatedEntity = null;
		
		try {
			manager.getTransaction().begin();
			updatedEntity = manager.merge( entity );
			manager.flush();
			manager.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			manager.getTransaction().rollback();
		}
		
		return updatedEntity;
	}

	public void delete(int id) {
		session.flush();
		session.clear();
		
		try {
			T entity = getById(id);
			manager.getTransaction().begin();
			manager.remove( entity );
			manager.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			manager.getTransaction().rollback();
		}
	}

	public List<T> findAll() {
		return manager.createQuery(("From " + getTypeClass().getName()))
				.getResultList();
	}

	protected Class<?> getTypeClass() {
		Class<?> clazz = (Class<?>) ((ParameterizedType) this.getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		return clazz;
	}
	
	protected Criteria createCriteria(){
		return session.createCriteria( getTypeClass() );
	}

}